package org.scep.model;

import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.io.File;
import java.io.IOException;

import org.scep.servlet.ServerServlet;

public class ServerManager
{
	private String filePath; // 文件保存路径
	private String fileName; // 保存时的文件名
	private int threadNum; // 线程数
	private long startPosition[];//分块开始指针
	private ServerFileHandle[] uphandles;
	private TimeoutThread tt;
	
	private PropertyChangeSupport pcs = new PropertyChangeSupport(this); 
	
	public ServerManager(String path, String name, int threadNum, long startPosition[]) throws IOException
	{
		if(path == null || name == null || threadNum < 1 || startPosition == null)
			throw new IllegalArgumentException("is not collect in param [path, name, threadNum, startPosition],check it!");
		
		if(threadNum != startPosition.length)
			throw new IllegalArgumentException("threadNum is not equal width startPosition's length!");
		
		this.filePath = path;
		this.fileName = name;
		this.threadNum = threadNum;
		this.startPosition = startPosition;
		init();
	}
	
	private void init() throws IOException{
		uphandles = new ServerFileHandle[this.threadNum];
		for (int i = 0; i < this.threadNum; i++){
			uphandles[i] = new ServerFileHandle( filePath + File.separator + fileName, startPosition[i], i);
		}
	}
	
	public boolean write(int id, byte[] b, int length, String timestamp){
		if(id < 0 || id > uphandles.length - 1)
			throw new IllegalArgumentException("the id is out of startPosition's range!");
		
		if(tt == null){
			tt = new TimeoutThread(ServerServlet.TIME_OUT);//set timeout 30s
			tt.start();
		}
		
		tt.reset();//reset the timeout thread when write
		
		try{
			uphandles[id].write(b, length, timestamp);
		}catch(IOException ioe){
			ioe.printStackTrace();
			return false;
		}
		
		return true;
	}
	
	public void close(){
		for (int i = 0; i < this.uphandles.length; i++){
			try{
				uphandles[i].close();
			}
			catch (IOException e){
				e.printStackTrace();
			}
		}
		
		if(tt != null){
			tt.setCancel();
			tt = null;
		}
	}
	
	class TimeoutThread extends Thread{
		
		private boolean recount = true;
		private boolean cancel = false;
		private Object lock = new Object();
		private long timeout;
		
		public TimeoutThread(long timeout){
			this.timeout = timeout;
		}
		
		public void run(){
			while(true){
				try {
					recount = false;
					Thread.sleep(timeout);
					
					synchronized(lock){
						if(!recount){
							if(!cancel){
								pcs.firePropertyChange(ServerServlet.CLOSE_PRO, null, fileName);
								System.out.println("the upload connection [" + fileName + "] is timeout.");
							}
							break;
						}
					}
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
		
		public void reset(){
			synchronized(lock){
				recount = true;
			}
		}
		
		public synchronized void setCancel(){
			cancel = true;
		}
		
	}

	public void addPropertyChangeListener(PropertyChangeListener l) {
		pcs.addPropertyChangeListener(l);
	}

	public void removePropertyChangeListener(PropertyChangeListener l) {
		pcs.removePropertyChangeListener(l);
	}
}
